#include "Battery.h"

namespace BulletScript
{

using namespace bs;

// ----------------------------------------------------------------------------
Battery::Battery(Machine* machine)
	: mMachine(machine)
	, mCount(0)
{
	mBullets.resize(BATTERY_SIZE);
}
// ----------------------------------------------------------------------------
UserTypeBase* Battery::EmitAngle(float x, float y, float angle, const float* args)
{
	Bullet b;
	b._active = 1;

	b.x = x;
	b.y = y;
	b.speed = args[-1];
	b.angle = args[-2];

	if (b.angle < 0.0f)
		b.angle += 360.0f;

	b.vx = sin(b.angle * 3.14159 / 180.0) * args[-1];
	b.vy = cos(b.angle * 3.14159 / 180.0) * args[-1];

	b.red = 1.0f;
	b.green = 1.0f;
	b.blue = 1.0f;
	b.alpha = 1.0f;

	size_t count = mSpawnedBullets.size();
	mSpawnedBullets.push_back(b);

	return &(mSpawnedBullets[count]);
}
// --------------------------------------------------------------------------------
UserTypeBase* Battery::EmitTarget(float x, float y, float angle, const float* args)
{
	Bullet b;
	b._active = 1;

	b.x = x;
	b.y = y;
	b.speed = args[-1];

	float dx = args[-4] - x;
	float dy = args[-3] - y;

	float tgtAngle = (float) atan2(dy, -dx) * bs::RAD_TO_DEG - 90.0f + args[-2];
	if (tgtAngle < 0.0f)
		tgtAngle += 360.0f;

	b.angle = tgtAngle;

	b.vx = sin(b.angle * 3.14159 / 180.0) * args[-1];
	b.vy = cos(b.angle * 3.14159 / 180.0) * args[-1];

	b.red = 1.0f;
	b.green = 1.0f;
	b.blue = 1.0f;
	b.alpha = 1.0f;

	size_t count = mSpawnedBullets.size();
	mSpawnedBullets.push_back(b);

	return &(mSpawnedBullets[count]);
}
// --------------------------------------------------------------------------------
void Battery::KillBullet(bs::UserTypeBase* object)
{
	Bullet* b = static_cast<Bullet*>(object);
	
	b->_active = 0;
	mMachine->releaseType(b);
}
// --------------------------------------------------------------------------------
void Battery::AddSpawnedBullets()
{
	size_t capacity = mBullets.capacity();
	size_t targetSize = mCount + mSpawnedBullets.size();
	if (targetSize > capacity)
	{
		size_t doubleSize = capacity * 2;
		size_t newSize = targetSize > (doubleSize) ? targetSize : doubleSize;
		mBullets.resize(newSize);
	}

	for (size_t i = 0; i < mSpawnedBullets.size(); ++i)
		mBullets[mCount++] = mSpawnedBullets[i];

	mSpawnedBullets.clear();
}
// ----------------------------------------------------------------------------
int Battery::UpdateBullets(float frameTime)
{
	int tCount = 0;
	for (int i = 0; i < mCount; ++i)
	{
		Bullet &b = mBullets[i];
		if (b._active)
		{
			// Apply normal movement update
			b.x += b.vx * frameTime;
			b.y += b.vy * frameTime;

			// bulletscript: apply affectors and control functions
			mMachine->updateType(&b, b.x, b.y, b.angle, frameTime);

			// Check for death
			// TODO: ...

			// Bullet is alive, add back to array
			if (i != tCount)
				mBullets[tCount] = mBullets[i];

			tCount++;
		}
	}

	return tCount;
}
// ----------------------------------------------------------------------------
void Battery::Update(float frameTime)
{
	AddSpawnedBullets();
	mCount = UpdateBullets(frameTime);
}
// ----------------------------------------------------------------------------

}